



function getVariableByName(name) {
	for (var i=0; i<variables.length; i++) {
		if (variables[i].name == name) {
			return variables[i];
		}
	}
	return false;
}

function getVariableFromElement(elm) {
	while (elm) {
		if (elm.className) {
			if (elm.className.indexOf("variable-container")!=-1) {
				break;
			}
		}
		elm = elm.parentNode;
	}
	var id = elm.getAttribute("id");

	//Extract name part
	var name = id.substring("variable_".length, id.length);

	return getVariableByName(name);
}


function Variable(name, type) {
	this.name  	= name;
	this.type  	= type;
	this.usesMacro 	= false;
	this.value 	= null;

	this.toXML = function(tab) {
		var xml = "";

		var typeId    = getTypeIdFromDisplayName(this.type);
		var typeLabel = typeLookup[typeId];
		if (!typeLabel) {
			//Enumerable, remove parantheses
			typeLabel = this.type.substring(1, this.type.length-1);
		}

		var macroStr = "";
		if (this.usesMacro) {
			macroStr = " uses-macro=\""+this.usesMacro+"\"";
		}

		xml += tab+"<variable name=\""+this.name+"\" type=\""+typeLabel+"\""+macroStr+">\n";

		if (!this.usesMacro) {

			//Find value container
			var tbody = $("variable_"+this.name).firstChild;
			var currentNode = tbody.childNodes[2].childNodes[1].firstChild;

			var value = null;

			if (typeId & TYPE_DATERANGE) {
				value = getDateRangeString(currentNode);

			} else if (typeId & TYPE_DATE) {
				value = getDateString(currentNode);

			} else if ( (typeId & TYPE_INT) || (typeId & TYPE_FLOAT) || (typeId & TYPE_STRING) ) {
				value = getPrimitiveString(currentNode);

			} else {

				//Enumerable or user-defined type
				var selector = currentNode;
				value = selector.options[selector.options.selectedIndex].value;
			}

			xml += tab+"\t"+value+"\n";
		}

		xml += tab+"</variable>\n";
		return xml;
	}
}



function repaintVariableValue(parent, newType, initValue, useMacro) {

	//Check if this is an enumerable
	var enum = isEnum(newType);
	if (enum) {

		//Just present a selector
		var selector = document.createElement("select");

		for (var i=0; i<enum.length; i++) {
			selector.options[i] = new Option(enum[i], enum[i]);
		}

		parent.appendChild(selector);

		selectOption(selector, initValue);


	} else {

		var typeId = getTypeIdFromDisplayName(newType);

		if (typeId & TYPE_DATERANGE) {

			//Date Range
			addDateRange(parent, false, initValue);

		} else if (typeId & TYPE_DATE) {

			//Single Date
			addDate(parent, false, initValue);

		} else if ( (typeId & TYPE_INT) || (typeId & TYPE_FLOAT) || (typeId & TYPE_STRING) ) {

			//Primitive
			addPrimitive(parent, false, initValue);

		} else {

			//A user-defined type
			var selector = document.createElement("select");

			var values = fillType(typeId);
			var i=0;
			for (id in values) {
				selector.options[i] = new Option(values[id], id);
				i++;
			}
			parent.appendChild(selector);

			selectOption(selector, initValue);

		}

		var macros = getMacros(typeId);
		if (macros.length > 0) {

			var div = document.createElement("div");
			div.style.marginBottom = "10px";
			parent.appendChild(div);

			div.appendChild(document.createTextNode("or use macro: "));

			var macroSelector = document.createElement("select");
			macroSelector.className = "macro-selector";

			//'No macro' -option
			var opt = document.createElement("option");
			opt.value = "null";
			opt.appendChild(document.createTextNode("<no macro>"));
			macroSelector.appendChild(opt);

			for (var i=0; i<macros.length; i++) {
				var opt = document.createElement("option");
				opt.value = macros[i][0];
				opt.appendChild(document.createTextNode(macros[i][0]));
				macroSelector.appendChild(opt);
			}

			div.appendChild(macroSelector);
			Event.observe(macroSelector, "change", clickChangeMacroSelector);

			selectOption(macroSelector, useMacro);
			setMacro(macroSelector);

		}
	}

}




function setMacro(selector) {
	var newMacro = selector.options[selector.options.selectedIndex].value;
	var variable = getVariableFromElement(selector);

	var enableType = false;
	if (newMacro == "null") {
		enableType = true;
		variable.usesMacro = false;
	} else {
		enableType = false;
		variable.usesMacro = newMacro;
	}

	var parentTd = selector.parentNode.parentNode;

	//Recursively disable input and select nodes
	enableNodesOfType(parentTd, new Array("input", "select"), enableType, "macro-selector");
}


function clickChangeMacroSelector(evt) {
	var selector = Event.findElement(evt);
	setMacro(selector);
}

/* Deprecated */
function clickChangeVariable(evt) {
	var selector = Event.findElement(evt);
	var newType  = selector.options[selector.options.selectedIndex].value;

	//Update object representation
	var variable = getVariableFromElement(selector);
	variable.type = newType;


	var td2Value = selector.parentNode.parentNode.parentNode.childNodes[2].childNodes[1];

	//Clear current content
	removeChildren(td2Value);

	repaintVariableValue(td2Value, newType);
}

function getAllTypes() {
	var types = new Array();

	//Add regular types
	for (typeId in typeLookup) {
		if ( (typeId != 0) && (typeId != 1) ) {
			types.push(typeDisplayNameLookup[typeId]);
		}
	}

	//Add all unique enumerables
	for (var i=0; i<queries.length; i++) {
		for (paramName in queries[i].params) {
			var paramType = queries[i].params[paramName];
			if (typeof(paramType) == "object") {
				var enumStr = "(";
				for (var j=0; j<paramType.length; j++) {
					if (j > 0) {
						enumStr += ",";
					}
					enumStr += paramType[j];
				}
				enumStr += ")";

				if (types.has(enumStr) == -1) {
					types.push(enumStr);
				}
			}
		}
	}

	return types;
}


function removeVariableClick(evt) {
	var elm = Event.findElement(evt);

	var removerDiv 		= elm.parentNode;
	var variableTable 	= removerDiv.nextSibling;
	var endHr 		= variableTable.nextSibling;
	var workbench  		= removerDiv.parentNode;

	workbench.removeChild(removerDiv);
	workbench.removeChild(variableTable);
	workbench.removeChild(endHr);

	var variableInstance = getVariableFromElement(variableTable);
	for (var i=0; i<variables.length; i++) {
		if (variables[i] == variableInstance) {
			variables.splice(i, 1);
			break;
		}
	}



	var typeDef = isEnum(variableInstance.type);
	if (!typeDef) {
		typeDef = getTypeIdFromDisplayName(variableInstance.type);
	}

	EventHandler.fireEvent("remvar", {"type":typeDef, "name":variableInstance.name});
}


function addVariableClick(evt) {


	//Sanity check
	var variableName = $("variable-name").value;
	var variableType = $("variable-type").value;
	if (variableName == "") {
		showError("Variables requires a name");
		return;
	}

	for (var i=0; i<variables.length; i++) {
		if (variables[i].name == variableName) {
			showError("\""+variableName+"\" is not a unique variable name");
			return;
		}
	}


	//Clean-up
	$("variable-name").value = "";
	$("variable-name-input").style.visibility = "hidden";

	addVariable(variableName, variableType, null, false);
}


function addVariable(variableName, variableType, initValue, useMacro) {


	var wb = $("variable_workbench");


	//Variable remover
	var div = document.createElement("div");
	div.style.marginLeft = "10px";
	wb.appendChild(div);

	var removeHref = document.createElement("a");
	removeHref.href = "javascript:;";
	var removeImg = document.createElement("img");
	removeImg.src = "img/silk/delete.png";
	removeImg.style.border = "0px";
	removeImg.style.marginRight = "6px";
	removeHref.appendChild(removeImg);
	removeHref.appendChild(document.createTextNode("Remove"));
	div.appendChild(removeHref);
	Event.observe(removeHref, "click", removeVariableClick);


	//Add variable
	var container	 = document.createElement("table");
	container.className = "variable-container";
	container.setAttribute("id", "variable_"+variableName);
	container.style.marginLeft = "10px";

	var tbody 	 = document.createElement("tbody");

	var trType 	 = document.createElement("tr");
	var trName 	 = document.createElement("tr");
	var trValue 	 = document.createElement("tr");

	var td1Type 	 = document.createElement("td");
	var td1Name 	 = document.createElement("td");
	var td1Value 	 = document.createElement("td");

	var td2Type 	 = document.createElement("td");
	var td2Name 	 = document.createElement("td");
	var td2Value 	 = document.createElement("td");





	// ---------------------------------------
	// ROW: Type

	// TD1
	td1Type.appendChild(document.createTextNode("Type:"));

	// TD2
	var typeInput = document.createElement("input");
	typeInput.value = variableType;
	typeInput.disabled = true;
	td2Type.appendChild(typeInput);
	// ---------------------------------------



	// ---------------------------------------
	// ROW: Name

	// TD1
	td1Name.appendChild(document.createTextNode("Name:"));

	// TD2
	var nameInput = document.createElement("input");
	nameInput.value = variableName;
	nameInput.disabled = true;
	td2Name.appendChild(nameInput);
	// ---------------------------------------



	// ---------------------------------------
	// ROW: Value

	// TD1
	td1Value.appendChild(document.createTextNode("Value:"));
	td1Value.vAlign = "top";

	// TD2
	// ---------------------------------------




	trType.appendChild(td1Type);
	trType.appendChild(td2Type);

	trName.appendChild(td1Name);
	trName.appendChild(td2Name);

	trValue.appendChild(td1Value);
	trValue.appendChild(td2Value);

	tbody.appendChild(trType);
	tbody.appendChild(trName);
	tbody.appendChild(trValue);

	container.appendChild(tbody);
	wb.appendChild(container);


	//Variable delimiter
	wb.appendChild(document.createElement("hr"));


	variables.push(new Variable(variableName, variableType));

	repaintVariableValue(td2Value, variableType, initValue, useMacro);



	//Notify queries that a new variable is available
	var typeDef = isEnum(variableType);
	if (!typeDef) {
		typeDef = getTypeIdFromDisplayName(variableType);
	}


	EventHandler.fireEvent("addvar", {"type":typeDef, "name":variableName});
}




function showVariableNameInput(evt) {

	var x = findPosX($("variable_workbench_header"));
	var y = findPosY($("variable_workbench_header"));
	var w = parseInt($("variable_workbench_header").offsetWidth);
	var h = parseInt($("variable_workbench_header").offsetHeight);
	var inputWidth = parseInt($("variable-name-input").offsetWidth);

	$("variable-name-input").style.visibility = "visible";
	$("variable-name-input").style.top 	  = y+h + "px";
	$("variable-name-input").style.left 	  = x+w-inputWidth + "px";
}


function hideVariableNameInput(evt) {
	$("variable-name-input").style.visibility = "hidden";
	$("variable-name").value = "";
	//XXX reset type selector as well
}



function createVariableWorkbench() {

	var container = document.createElement("div");
	container.className = "content_table";
	container.setAttribute("id", "variable_workbench");
	$("report_container").appendChild(container);


	//Render title row
	var titleTable 	= document.createElement("table");
	var titleTbody 	= document.createElement("tbody");
	var tr 		= document.createElement("tr");
	var tdTitle 	= document.createElement("td");
	var tdActions 	= document.createElement("td");
	tr.appendChild(tdTitle);
	tr.appendChild(tdActions);
	titleTbody.appendChild(tr);
	titleTable.appendChild(titleTbody);
	container.appendChild(titleTable);

	titleTable.className = "table_header";
	titleTable.setAttribute("id", "variable_workbench_header");

	//First column
	var titleElm = document.createElement("h3");
	titleElm.appendChild(document.createTextNode("Variables"));
	tdTitle.appendChild(titleElm);

	//Second column
	tdActions.style.textAlign = "right";
	var addHref = document.createElement("a");
	addHref.href = "javascript:;";
	var addImg = document.createElement("img");
	addImg.src = "img/silk/add.png";
	addImg.style.border = "0px";
	addImg.style.marginRight = "6px";
	addHref.appendChild(addImg);
	addHref.appendChild(document.createTextNode("Add variable"));
	tdActions.appendChild(addHref);
	Event.observe(addHref, "click", showVariableNameInput);



	//Variable delimiter
	container.appendChild(document.createElement("hr"));

}

function createVariableAdder() {

	var variableNameInput = document.createElement("div");
	variableNameInput.setAttribute("id", "variable-name-input");
	variableNameInput.className = "variable-name-input";



	var table = document.createElement("table");
	var tbody = document.createElement("tbody");
	table.appendChild(tbody);
	variableNameInput.appendChild(table);



	//Create type row
	var tr  = document.createElement("tr"); tbody.appendChild(tr);
	var td1 = document.createElement("td"); tr.appendChild(td1);
	var td2 = document.createElement("td"); tr.appendChild(td2);

	td1.appendChild(document.createTextNode("Type: "));

	var typeSelector = document.createElement("select");
	typeSelector.setAttribute("id", "variable-type");
	var types = getAllTypes();
	for (var i=0; i<types.length; i++) {
		var opt = document.createElement("option");
		opt.value = types[i];
		opt.appendChild(document.createTextNode(types[i]));
		typeSelector.appendChild(opt);
	}

	td2.appendChild(typeSelector);



	//Create name row
	var tr  = document.createElement("tr"); tbody.appendChild(tr);
	var td1 = document.createElement("td"); tr.appendChild(td1);
	var td2 = document.createElement("td"); tr.appendChild(td2);

	td1.appendChild(document.createTextNode("Name: "));

	var nameInput = document.createElement("input");
	nameInput.setAttribute("id", "variable-name");
	td2.appendChild(nameInput);



	//Create action row
	var tr  = document.createElement("tr"); tbody.appendChild(tr);
	var td1 = document.createElement("td"); tr.appendChild(td1);
	var td2 = document.createElement("td"); tr.appendChild(td2);

	td2.style.textAlign = "right";

	var nameCancel = document.createElement("a");
	nameCancel.href = "javascript:;";
	nameCancel.appendChild(document.createTextNode("Cancel"));
	td2.appendChild(nameCancel);

	var nameAdd = document.createElement("a");
	nameAdd.href = "javascript:;";
	nameAdd.style.marginLeft = "10px";
	nameAdd.appendChild(document.createTextNode("Add"));
	td2.appendChild(nameAdd);




	body.appendChild(variableNameInput);
	Event.observe(nameAdd, "click", addVariableClick);
	Event.observe(nameCancel, "click", hideVariableNameInput);

}


function initVariables() {

	EventHandler.defineEvent("addvar");
	EventHandler.defineEvent("remvar");

	createVariableWorkbench()

	createVariableAdder()

}